package api

import (
	"fmt"
	"errors"
	"strings"
	"reflect"
	"runtime"
	"kumachan/interpreter/runtime/rt"
)

var nativeFunctionRegistry = [] interface{} {
	__None,
	// assert
	__UnsafeArbitraryValue,
	__Panic,
	__Assert,
	__ForceUnwrap,
	// bitwise
	__AndBit,  __AndByte, __AndWord,  __AndDword, __AndQword,
	__OrBit,   __OrByte,  __OrWord,   __OrDword,  __OrQword,
	__NotBit,  __NotByte, __NotWord,  __NotDword, __NotQword,
	__XorBit,  __XorByte, __XorWord,  __XorDword, __XorQword,
	__ShlByte, __ShlWord, __ShlDword, __ShlQword,
	__ShrByte, __ShrWord, __ShrDword, __ShrQword,
	// comparison
	__GeneralEqual,
	__UnionIndexEqual,
	// container
	__SeqReverse,
	__SeqCount, __SeqInclusiveRange,
	__SeqShift, __SeqNil, __SeqCons,
	__SeqToList, __SeqWithIndex,
	__SeqMap, __SeqDeflateMap, __SeqFilter, __SeqFlatMap,
	__SeqChunk, __SeqConcat,
	__SeqScan, __SeqReduce, __SeqSome, __SeqEvery,
	__SeqFindFirst, __SeqGetFirst,
	__SeqZip,     __SeqZipLongest,
	__SeqZipList, __SeqZipLongestList,
	__ListToSeq,
	__ListLength, __ListEmpty,
	__ListReverse, __ListShift, __ListPop,
	__Set, __SetValues, __SetHas,
	__Map, __MapEntries, __MapLookup,
	__MapInsert,
	__MapDelete,
	__ProjRef_f,
	__CaseRef_f,
	// debugging
	__DebugLog,
	// error
	__Error,
	__ErrorToString, __ErrorData,
	__ErrorWrap,
	__ErrorNumOfIoBytes, __ErrorIsEOF, __ErrorIsClosedPipe,
	// numeric
	__IntegerPlus, __IntegerMinus, __IntegerNegate, __IntegerMul,
	__IntegerQuo, __IntegerRem,
	__IntegerPow,
	__NumberForceMinus,
	__Plus, __Minus, __Negate, __Mul,
	__Quo, __Rem,
	__Floor, __Ceil, __Round,
	__Pow, __Sqrt, __Cbrt,
	__Exp, __Log,
	__Sin, __Cos, __Tan,
	__Asin, __Acos, __Atan, __Atan2,
	__IntegerEqual, __IntegerLessThan, __IntegerCompare,
	__FloatEqual,   __FloatLessThan,
	__IntegerToString,
	__FloatToString, __Percentage0, __Percentage1, __Percentage2,
	__NormalFloatParse,
	__IntegerToFloat,
	__FloatToInt,
	__IntegerToMaybeNumber,
	__FloatToMaybeNormalFloat,
	// string
	__StringFromChar, __StringFromListOfChar,
	__CharEqual, __CharFromInt,
	__StringToSeq,
	__StringEqual, __StringLessThan, __StringCompare,
	__EncodeUtf8, __DecodeUtf8, __DecodeUtf8Casual,
	__Quote, __Unquote,
	__StringConcat,
	__StringUtf8Length,
	__StringShift, __StringShiftPrefix,
	__StringSplit, __StringJoin,
	__StringTrim, __StringTrimLeft, __StringTrimRight,
	__StringTrimPrefix, __StringTrimSuffix,
	__StringHasPrefix,  __StringHasSuffix, __StringContains,
	// rx
	__Sink, __Blackhole, __SinkEmit, __SinkAdapt, __SinkDebounce,
	__Bus, __BusIn, __BusOut,
	__Reactive, __ReactiveFromSinkComputed, __ReactiveUpdate, __ReactiveMorph,
	__Mutable, __MutableRead, __MutableWrite,
	__SourceFromObservable, __Connect,
	__ComputedFromSource,
	__ComputedSample, __ComputedWithValueFrom,
	__ComputedLiftAx, __ComputedCombine, __ComputedCombineList,
	__ComputedMap, __ComputedSwitchMap,
	__ComputedListMap, __ComputedMemoMap,
	__Do, __Await, __With, __WithCanceller, __OnCancel,
	__Go, __Async, __Return, __Yield, __Const, __Throw,
	__Random01, __PUID, __UUID, __Wait, __Tick, __Crash,
	__Catch, __CatchNone, __CatchComplete, __CatchRetry, __CatchThrow,
	__ObservableStartWith,
	__ObservableTakeOneAsSingle,
	__ObservableWaitComplete, __ObservableForever,
	__ObservableMap, __ObservableDeflateMap, __ObservableFilter,
	__ObservableScan, __ObservableReduce,
	__ObservableDebounce,
	__ObservableSwitchMap, __ObservableExhaustMap,
	__ObservableMergeMap, __ObservableConcatMap, __ObservableMixMap,
	__ObservableMerge, __ObservableConcat,
	__ObservableDistinctUntilChanged,
	__ObservableWithLatestFrom,
	__ObservableCombineLatest, __ObservableCombineLatestList,
	// sys
	__SysUrlParse,
	__SysHttpGet,
	__SysHttpResStatus, __SysHttpResHeader, __SysHttpResBody,
	__SysUTC, __SysLocalTime,
	__SysPlatformInfo, __SysLocale,
	__SysCwd, __SysEntryModuleDirPath,
	__SysEnv, __SysArgs,
	__SysStdin, __SysStdout, __SysStderr,
	__SysPathParse, __SysPathToString, __SysPathJoin,
	__SysWalkDir, __SysListDir,
	__SysOpenFilePersist,
	__SysFileClose,
	__SysFileGetState, __SysFileSeekStart, __SysFileSeekDelta, __SysFileSeekEnd,
	__SysFileRead, __SysFileWrite,
	__SysFileReadAll, __SysFileReadChar, __SysFileReadLine, __SysFileReadLines,
	__SysFileWriteString, __SysFileWriteLine,
	__SysExit,
	// ui
	__UiGetAssetUrl,
	__UiInteractWithWindow,
	__UiModalGetColor,
	__UiModalGetLine, __UiModalGetSmallInteger, __UiModalGetNormalFloat,
	__UiStaticComponent,
	__UiVdomNode,
	__UiVdomNodeWithAttrs, __UiVdomNodeWithStyles, __UiVdomNodeWithEvents,
	__UiVdomNodeWithContent,
	__UiVdomStyles, __UiVdomAttrs, __UiVdomEvents, __UiVdomEventHandler,
	__UiVdomText, __UiVdomChildren,
	__UiEventPayloadGetBool,
	__UiEventPayloadGetString,
	__UiEventPayloadGetFloat,
	__UiEventPayloadGetInt,
}

var nativeFunctionMap = (func() (map[string] rt.NativeFunction) {
	var m = make(map[string] rt.NativeFunction)
	for _, f := range nativeFunctionRegistry {
		var obj = runtime.FuncForPC(reflect.ValueOf(f).Pointer())
		var name = strings.Split(obj.Name(), ".")[1]
		var _, exists = m[name]
		if exists { panic("duplicate native function name " + name) }
		m[name] = rt.AdaptNativeFunction(f)
	}
	return m
})()
var unusedNativeFunctions = (func() (map[string] struct{}) {
	var m = make(map[string] struct{})
	for id := range nativeFunctionMap {
		m[id] = struct{}{}
	}
	return m
})()
func GetNativeFunctionValue(id string) rt.NativeFunction {
	var f, exists = nativeFunctionMap[id]
	if !(exists) { panic(fmt.Sprintf("no such native function: %s", id)) }
	delete(unusedNativeFunctions, id)
	return f
}
func CheckUnusedNativeFunctions() error {
	var unused = make([] string, 0)
	for id := range unusedNativeFunctions {
		unused = append(unused, id)
	}
	if len(unused) > 0 {
		var all = strings.Join(unused, ", ")
		return errors.New(fmt.Sprintf("unused native function(s): %s", all))
	} else {
		return nil
	}
}


